package com.weijin.bookborrowmanagesystem.service.impl;

import com.weijin.bookborrowmanagesystem.common.Result;
import com.weijin.bookborrowmanagesystem.enums.BookEnum;
import com.weijin.bookborrowmanagesystem.enums.ExceptionEnum;
import com.weijin.bookborrowmanagesystem.exception.AppException;
import com.weijin.bookborrowmanagesystem.factory.BorrowFactory;
import com.weijin.bookborrowmanagesystem.factory.BorrowUtil;
import com.weijin.bookborrowmanagesystem.mapper.BookMapper;
import com.weijin.bookborrowmanagesystem.mapper.BorrowMapper;
import com.weijin.bookborrowmanagesystem.mapper.UserMapper;
import com.weijin.bookborrowmanagesystem.pojo.Book;
import com.weijin.bookborrowmanagesystem.pojo.Borrow;
import com.weijin.bookborrowmanagesystem.pojo.User;
import com.weijin.bookborrowmanagesystem.service.BorrowService;
import com.weijin.bookborrowmanagesystem.utils.DateTimeUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @Author WeiJin
 * @Version 1.0
 * @Date 2025/3/13 10:39
 */
@Service
public class BorrowServiceImpl implements BorrowService {
    @Resource
    private BorrowMapper borrowMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private BookMapper bookMapper;
    @Resource
    private BorrowFactory borrowFactory;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<String> borrowBook(Borrow borrow) {
        if (Objects.isNull(borrow)) {
            throw new AppException(ExceptionEnum.PARAM_ERROR);
        }
        if (Objects.isNull(borrow.getBookId())) {
            throw new AppException(ExceptionEnum.BOOK_ID_NOT_NULL);
        }
        if (Objects.isNull(borrow.getUserId())) {
            throw new AppException(ExceptionEnum.USER_ID_NOT_NULL);
        }
        if (Objects.isNull(borrow.getDays())) {
            throw new AppException(ExceptionEnum.BORROW_DAY_NOT_NULL);
        }
        User user = userMapper.selectById(borrow.getUserId());
        if (Objects.isNull(user)) {
            throw new AppException(ExceptionEnum.USER_NOT_EXIST);
        }
        //获取数据库的图书信息
        Book book = bookMapper.selectById(borrow.getBookId());
        if (Objects.isNull(book)) {
            throw new AppException(ExceptionEnum.BOOK_NOT_EXIST);
        }
        if (!Objects.equals(book.getStatus().name(), BookEnum.AVAILABLE.name())) {
            throw new AppException(ExceptionEnum.BOOK_NOT_BORROW);
        }
        if (book.getStock() == 0) {
            throw new AppException(ExceptionEnum.STOCK_IS_NULL);
        }
        //未归返的书籍不能重复借
        Borrow dataBorrow = borrowMapper.selectUnReturnByUserAndBook(borrow.getUserId(), borrow.getBookId());
        if (Objects.nonNull(dataBorrow)) {
            throw new AppException(ExceptionEnum.NOT_REPEAT_BORROW_SAME_BOOK);
        }
        // 获取该用户未归还书籍数量
        int count = borrowMapper.selectUnReturnCount(borrow.getUserId());
        //工厂模式：根据角色返回借阅对象
        BorrowUtil borrowFactoryBorrow = borrowFactory.getBorrow(user.getRole());
        boolean flag = borrowFactoryBorrow.isAbleBorrow(count);
        if (!flag) {
            throw new AppException(ExceptionEnum.BORROW_NUM_LIMITED);
        }
        borrow.setBorrowTime(DateTimeUtil.getDateTime());
        int i = borrowMapper.insert(borrow);
        i += bookMapper.updateStockById(book.getId(), book.getStock() - 1);
        //判断库存是否0
        if (book.getStock() - 1 == 0) {
            i += bookMapper.updateStatus(book.getId(), BookEnum.BORROWED);
        }
        return i >= 2 ? Result.success("借阅成功") : Result.failed("借阅失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<String> returnBook(Borrow borrow) {
        Borrow dataBorrow = borrowMapper.selectUnReturnByUserAndBook(borrow.getUserId(), borrow.getBookId());
        if (Objects.isNull(dataBorrow)) {
            throw new AppException(ExceptionEnum.NOT_BORROW_RECORD);
        }
        LocalDateTime returnTime = DateTimeUtil.getDateTime();

        //还书借书相差天数
        long days = DateTimeUtil.daysBetween(dataBorrow.getBorrowTime(), returnTime);
        Borrow updateBorrow = new Borrow();
        updateBorrow.setId(dataBorrow.getId());
        updateBorrow.setReturnTime(returnTime);
        //构建罚款金额
        boolean isFine = days > dataBorrow.getDays();
        if (isFine) {
            updateBorrow.setMoney((days - dataBorrow.getDays()) * 1.0);
        }
        //获取图书信息
        Book book = bookMapper.selectById(borrow.getBookId());
        //修改还书日期及罚款金额
        int i = borrowMapper.updateCondition(updateBorrow);
        //库存+1
        i += bookMapper.updateStockById(borrow.getBookId(), book.getStock() + 1);
        //判断库存是否为0，为0图书状态改为可借
        if (book.getStock() - 1 == 0) {
            i += bookMapper.updateStatus(book.getId(), BookEnum.AVAILABLE);
        }
        //拼接还书成功，响应字符
        String text = isFine ? "还书成功，逾期" + (days - dataBorrow.getDays()) + "天，需缴纳罚款" +
                ((days - dataBorrow.getDays()) * 1.0) + "元！" : "还书成功";
        return i >= 2 ? Result.success(text) : Result.failed("还书失败");
    }

    @Override
    public Result<List<Borrow>> queryByUserId(Integer userId) {
        List<Borrow> list = borrowMapper.selectListCondition(userId);
        return Result.success("查询成功", list);
    }
}
